/*
 * Copyright (c) 2009, Jan Pastor. All Rights Reserved.
 */

package sk.jp.jitag.dao;

import java.util.Collection;
import java.util.List;

import sk.jp.jitag.dao.db4o.BaseEntity;
import sk.jp.jitag.dao.db4o.BaseEnum;
import sk.jp.jitag.model.File;
import sk.jp.jitag.model.config.Config;
import sk.jp.commons.exception.ApplicationException;

/**
 * DAO for JiTag application.
 */
public interface JitagDao extends Dao {

    /**
     * Result of file synchronization check.
     */
    enum FileSyncState {

        /**
         * File hash equals.
         */
        equals,

        /**
         * File hash is different.
         */
        changed,

        /**
         * Missing in database.
         */
        missing;
    }

    //----------------------------------------------------------------------

    /**
     * Set-up flag of files that they can be deleted because doesn't exists
     * in file-system.
     * @param fileExtensions
     */
    void markFilesForDelete(Collection<String> fileExtensions);

    /**
     * Performs check of synchronization state of specified file.
     * @param fileId file identifier.
     * @param fileHash file (on file-system) hash that correspond to its
     * current content.
     * @return synchronization state of file.
     */
    FileSyncState isChanged(Integer fileId, Integer fileHash);

    /**
     * Deletes files from database that have set-up flag for delete.
     * <p>See method {@link JitagDao#markFilesForDelete(Collection)}.
     * @return count of files deleted from database.
     */
    int deleteMarkedFiles();

    /**
     * Clear flag about file can be deleted because already doesn't exists
     * on file-system.
     * <p>See method {@link #markFilesForDelete(List)}.
     * @param fileId file identifier.
     */
    void unmarkFileForDeleteFlag(Integer fileId);

    /**
     * Save new file to database.
     * @param file to save.
     */
    void saveNewFile(File file);

    /**
     * Update attributes of existig (already persisted in database) file
     * identified by {@link File#id}.
     * @param file file update.
     */
    void updateChangedFile(File file);

    /**
     * Get enumeration item specified by code.
     * @param code item enumeration code, that is unique for enumeration type.
     * @param clazz entity type class.
     * @return enumeration item.
     * @throws ApplicationException if item of specified type and with specified code
     * was not found, or other error.
     */
    <T extends BaseEnum> T get(String code, Class<T> clazz);

    /**
     * Get enumeration item specified by code.
     * @param code item enumeration code, that is unique for enumeration type.
     * @param clazz entity type class.
     * @return enumeration item or null if enumeration item was not persisted before.
     */
    <T extends BaseEnum> T getOptional(String code, Class<T> clazz);

    /**
     * Get enumeration item specified by code.
     * @param code item enumeration code, that is unique for enumeration type.
     * @param clazz entity type class.
     * @param enumInstance enumeration instance of saved if no instance with
     * specified code was found in database.
     * @return enumeration item.
     */
    <T extends BaseEnum> T getOrNew(String code, Class<T> clazz, T enumInstance);

    /**
     * Get all instances of specified entity.
     * @param clazz entity type class.
     * @return a list of all persisted entities.
     */
    <T extends BaseEntity> List<T> getAll(Class<T> clazz);

    /**
     * Retrieve already persisted file by specified identifier ({@link File#id}).
     * @param fileId
     * @return file instance or null if not found.
     */
    File getFile(Integer fileId);

    /**
     * Loads configuration from database.
     * @return application configuration or null if no configuration was persisted yet.
     */
    Config getConfig();

    /**
     * Save/update application configuration.
     * @param config
     */
    void saveConfig(Config config);

    /**
     * Copy (make hot backup) of database file in current state.
     * @param newDbPath absolute path of new db file.
     */
    void copyDatabaseFile(String newDbPath);

}
